package cc.momas;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * @author Sod-Momas
 * @since 2020.01.16
 **/
@WebServlet(value = "/download")
public class DownloadServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 解决乱码,一般写在过滤器 filter里
        request.setCharacterEncoding(StandardCharsets.UTF_8.displayName());
        response.setCharacterEncoding(StandardCharsets.UTF_8.displayName());
        response.setContentType("text/html;charset=utf-8");

        // 获取文件
        Path file = Paths.get("E:\\Downloads\\测试文件.pdf");
        // 检测文件是否存在
        if (Files.notExists(file)) {
            response.getWriter().write("指定文件不存在:" + file.toAbsolutePath());
            return;
        }

        // 获取文件名
        String filename = file.getFileName().toString();
        // 获取文件大小,单位是byte
        long fileSize = Files.size(file);

        // 将文件名URL编码
        filename = URLEncoder.encode(filename, StandardCharsets.UTF_8.displayName());
        // 添加触发下载的前缀
        // 规范参考 : Content-Disposition https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Disposition
        String disposition = "attachment;filename*=utf-8'zh_cn'" + filename;

        // 添加 Content-Disposition 告诉浏览器数据展现的方式是附件下载,并且提供文件名
        response.addHeader("Content-Disposition", disposition);
        // 添加 Content-Length 告诉浏览器数据的长度,单位是 byte
        response.setContentLength((int) fileSize);
        // 添加 Content-Type 告诉浏览器这是一个二进制流
        response.setContentType("application/octet-stream");

        // 把文件从本地复制到 response 输出流输出给前端
        Files.copy(file, response.getOutputStream());
    }
}
